home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_100 / 101_01 / rally.c < prev    next >
Text File  |  1985-11-13  |  11KB  |  427 lines

  1. /*
  2.     H19 RALLY Game,        5/80    Steve Ward
  3.  
  4.     Works ONLY on Heathkit/Zenith H19/Z19 terminal
  5.                  (or H89 computer)
  6.  
  7.     Command format:
  8.  
  9.     A>rally [-rn] [-b] [mapname] <cr>
  10.  
  11.     where:    "n"  is an optional seed for the random number generator
  12.              (results in exactly the same minor track deviations each
  13.              time it is given with a particular track);
  14.              If "n" is omitted, then track deviations are totally
  15.              random for each session (but same for each run in any
  16.              single session.)
  17.  
  18.         "-b" is a debugging option doing Steve-knows-what.
  19.  
  20.         "mapname" specifies the map file to use for the track
  21.             (defaults to "rally.map").
  22. */
  23.  
  24.  
  25.             /* Hardware Dependent defines:        */
  26. #define    CRTDAT    0350      /* H19 data port            */
  27. #define    CRTSTA    0355      /* H19 status port            */
  28. #define INPMASK 0x01    /* input data ready mask        */
  29. #define OUTMASK 0x20    /* ready to transmit to H19 mask    */
  30.             /* END Hardware Dependent defines    */
  31.  
  32.             /* Note that the program is set up
  33.                assuming the status bits are active
  34.                HIGH...if yours are active low,
  35.                you'll have to go change the 
  36.                "putchar" function below.        */
  37.  
  38. #define    CARY    16        /* Y position of car.        */
  39. #define    IBAD    0
  40. #define    LSPEED    7        /* Line 25 label posns        */
  41. #define    LMILES    20
  42. #define    MAXSPD    9
  43. #define    SPDSCL    128
  44. #define    TENTHS    10        /* Number of lines per mile.    */
  45. #define    TICMIN    1920        /* Number of tics per minute.    */
  46.  
  47. char    Free[10000], *Freep;
  48.  
  49. char    CRTFrz, CRTChr;
  50. int    Miles;
  51. char    Pavement, Freeze, BFlag;
  52. char    CurX, CurY, SignY;
  53. int    CarX, CarDX;
  54. char    RevFlg, AltFlg;
  55. int    Speed, Tenths;
  56. char    Image[CARY*80+80];
  57. char    *ImPtr, *ImEnd;
  58. int    Seed;
  59. int    Ranno;
  60. char    InBuf[134], SavChr;
  61. int    SpTime[MAXSPD+1];
  62.  
  63. struct Road {
  64.     struct Node *Next;
  65.     char    active;
  66.     char    Token;
  67.     int    Windy;
  68.     int    Curvy;
  69.     int    Age;
  70.     int    ToGo;
  71.     char    Holes;
  72.     char    X;
  73.     char    dx;
  74.     char    width; } Road1, Road2;
  75.  
  76. struct Sign {
  77.     struct Node *Next;
  78.     char key;
  79.     char text[0]; };
  80.  
  81. struct Fork {
  82.     struct Node *Next;
  83.     char key;
  84.     char *Branch; };
  85.  
  86. struct Dist {
  87.     struct Node *Next;
  88.     char key;
  89.     char wid, curve, wind;
  90.     int miles; };
  91.  
  92. union Node {
  93.     struct Dist;
  94.     struct Fork;
  95.     struct Sign; } *Tag[128];
  96.  
  97. /*
  98.     This function assumes that both input and output
  99.     status bits on the H19 port are active (true) high.
  100.     If your serial port goes the other way, you'll have to
  101.     change two of the lines as follows:
  102.  
  103.      { if (INPMASK & (stat = inp(CRTSTA)))
  104.             goes to                (change #1)
  105.      { if (!(INPMASK & (stat = inp(CRTSTA))))
  106.  
  107.     AND 
  108.  
  109.         if (stat & OUTMASK) { ... }}}
  110.             becomes                (change #2)
  111.         if (!(stat & OUTMASK)) { ... }}}
  112. */
  113.  
  114. putchar(c)
  115.  {    char stat, ch;
  116.     for(;;)
  117.      { if (INPMASK & (stat = inp(CRTSTA)))
  118.         switch(ch = (0177 & inp(CRTDAT))) {
  119.         case 'S'-64:    CRTFrz=1; break;
  120.         case 'Q'-64:    CRTFrz=0; break;
  121.         case 'C'-64:    puts("\033z"); exit();
  122.         default:    CRTChr=ch; }
  123.        if (CRTFrz) continue;
  124.        if (stat & OUTMASK) { if (c) outp(CRTDAT, c); return; }}}
  125.  
  126.  
  127. char *new(size)
  128.  {    char *rr;
  129.     rr = Freep; Freep += size; return rr; }
  130.  
  131. struct Dist *NRoad(widx, curv, windx, dist)
  132.  {    struct Dist *rr;
  133.     rr = new(sizeof *rr);
  134.     rr->key = 'D';        rr->Next = 0;
  135.     rr->miles = dist;    rr->wid = widx;
  136.     rr->curve = curv;    rr->wind = windx;
  137.     return rr; }
  138.  
  139. struct Sign *NSign(txt)
  140.  char *txt;
  141.  {    int leng; char *cc, *dd;
  142.     struct Sign *ss;
  143.     leng = sizeof *ss; leng++;
  144.     for (cc=txt; *cc++; leng++);
  145.     ss = new(leng);        ss->key = 'S';        ss->Next = 0;
  146.     dd = &(ss->text); for (cc=txt; *dd++ = *cc++;);
  147.     return ss; }
  148.  
  149. struct Fork *NFork(kk)
  150.  {    struct Fork *ff;
  151.     ff = new(sizeof *ff); ff->key = kk;
  152.     ff->Next = 0;    ff->Branch = 0;
  153.     return ff; }
  154.  
  155. PrNode(nn)
  156.  struct Node *nn;
  157.  {    printf("Node %x: %c -> %x \r\n", nn, nn->key, nn->Next); }
  158.  
  159. char rdc()
  160.  {    char ch;
  161.     if (ch = SavChr) { SavChr=0; return ch; };
  162.     return (getc(InBuf)); }
  163.  
  164. char pkc()
  165.  {    return (SavChr = rdc()); }
  166.  
  167. int rdn()
  168.  {    int ans, ch;
  169.     ans = 0;
  170.     while (isdigit(pkc()))    ans = ans*10 + (rdc() - '0');
  171.     return ans; }
  172.  
  173. struct Dist *LRoad()
  174.  {    int w, c, iwid, dd;
  175.     char ch;
  176.     dd = rdn();
  177.     w = -1; c = -1; iwid = 20;
  178.     while (pkc() != '\n') switch(rdc())
  179.      {    case '~':    c++; continue;
  180.         case 'W':    iwid = rdn(); continue;
  181.         case '!':    w++; continue;
  182.         default:    continue; }
  183.     return NRoad(iwid, c, w, dd);
  184.  }
  185.  
  186. struct Dist *Load(name)
  187.  char *name;
  188.  {    char ch, buf[100], *cc;
  189.     struct Sign First, Ignore;
  190.     struct Node *it, *last;
  191.     puts("\033z");
  192.     SavChr = 0;
  193.     it = &First; First.key = '?';
  194.     if (fopen(name, InBuf) == -1)
  195.      { printf("Can't read %s\r\n", name); exit(); }
  196.  
  197.     while ((ch = rdc()) != 014) putchar(ch);
  198.     while ((ch = rdc()) != ('Z'-64))
  199.      { last = it;
  200.        switch(ch)
  201.         {    case '=':    Tag[rdc(InBuf)] = Freep; break;
  202.         case '|':    while (rdc() != '\n'); break;
  203.         case '"':    cc = buf;
  204.                 while (((ch = rdc()) != '"') &&
  205.                     (ch != '\n')) *cc++ = ch;
  206.                 *cc = 0;
  207.                 it->Next = NSign(buf); it = it->Next;
  208.                 break;
  209.         case '#':    it->Next = LRoad(); it = it->Next;
  210.                 break;
  211.  
  212.         case ':':    it->Next = rdc();
  213.         case '.':    it = &Ignore; break;
  214.  
  215.         case '>':    it->Next = NFork('R'); it = it->Next;
  216.                 it->Branch = rdc();
  217.                 break;
  218.         case '<':    it->Next = NFork('L'); it = it->Next;
  219.                 it->Branch = rdc();
  220.                 break;
  221.  
  222.         case ' ':    case '\n':    case '\r':    case '\t':
  223.         case '\f':    break;
  224.  
  225.         default:    puts("Illegal syntax: "); putchar(ch);
  226.                 while ((ch = rdc(InBuf)) != '\n') putchar(ch);
  227.                 puts("\n\r"); break; }}
  228.     NSign("Unbound label");
  229.     srand1("\033x1\033x5\033Y8   (type a character to start)");
  230.     if (!Seed) Seed = rand();    /* Do this only if "-r" option given
  231.                        without any argument.    */
  232.     bdos(3);
  233.     return First.Next; }
  234.  
  235. Exec(rr)
  236.  struct Road *rr;
  237.  {    int x, dir, tt, right, left;
  238.     union Node *nn;
  239.     nn = rr->Next;    rr->Next = nn->Next;
  240.     x = rr->X; dir = -1;
  241.  
  242.     switch (nn->key) {
  243.      case 'S':    right = x+(rr->width); left = 78-right;
  244.             x = x>left? 0:right+2;
  245.             printf("\033Y%c%c\033G %s \033F",
  246.                 SignY++, x+32, &(nn->text));
  247.             return;
  248.      case 'D':    rr->Age = 0;
  249.             if (nn->wind != 255) rr->Windy = ~(-1 << nn->wind);
  250.             if (nn->curve != 255) rr->Curvy = nn->curve;
  251.             rr->ToGo = nn->miles;
  252.             if (nn->wid != 255) rr->width = nn->wid; return;
  253.      case 'L':    dir = 1;
  254.      case 'R':    if (!Freeze) fork(nn->Branch, dir); return;
  255.              }
  256.  }
  257.  
  258. MoveTo(x, y) { puts("\033Y"); putchar(y+32); putchar(x+32); }
  259. SpeedL() { MoveTo(LSPEED, 24); putchar(Speed + '0'); }
  260. label(val, posn)
  261.  {    printf("\033Y8%c%d ", posn+32, val); }
  262.  
  263.  
  264. getchar()
  265.  {    char ch;
  266.     while (!(ch = CRTChr)) putchar(0);
  267.     CRTChr = 0; return ch; }
  268.  
  269. car(x)
  270.  {    puts("\033Y"); putchar(CARY+31); putchar(x+32);
  271.     puts(" "); }
  272.  
  273. roll()
  274.  {    puts("\033H\033L");
  275.     CurX=0; CurY=0;
  276.     if ((ImPtr += 80) == ImEnd) ImPtr = Image;
  277.     Pavement = ImPtr[CarX];
  278.     setmem(ImPtr, 80, IBAD); }
  279.  
  280. road(x, width, rdno)
  281.  {    char i, *cc;
  282.     puts("\033Y ");
  283.     putchar(32+x);
  284.     if (!RevFlg) { puts("\033p"); RevFlg=1; }
  285.     if (!AltFlg) { puts("\033F"); AltFlg=1; }
  286.     cc = &(ImPtr[x]);
  287.     for (i=width; i--;) { putchar('i'); *cc++ |= rdno; }}
  288.  
  289. /* Update a Road; returns 1 if finish line.    */
  290.  
  291. UpRd(rr)
  292.  struct Road *rr;
  293.  {    int ddx, left, right, curve, act, rough; unsigned i;
  294.     if (!(act = rr->active)) return 0;
  295.     (rr->ToGo)--;
  296.     while ((rr->ToGo) <= 0)
  297.      { if (i = (rr->Next))
  298.         {    if (i == '.') return 1;
  299.         if (i == '*') { rr->active = 0; return 0; }
  300.         if (i < 128)
  301.          { rr->Next = Tag[i];
  302.            if (BFlag) { puts("\033H\033G");
  303.                 putchar(i);
  304.                 puts("\033F"); }}
  305.         Exec(rr); }
  306.        else { rr->active = 0; return 0; }}
  307.     if (Freeze) rough=0;
  308.     else rough=1;
  309.     if (++(rr->Age) > 24)
  310.         if (!(Pavement & (rr->Token)))
  311.             { rr->active = 0; Freeze = 0; return 0; }
  312.     ddx = rr->dx;
  313.     left = rr->X; right = left+(rr->width);
  314.     if (left < 1) ddx = rough;
  315.     else if (right > 79) ddx = -rough;
  316.     else if ((!Freeze) && (!((rr->Windy) & Ranno)))
  317.      { curve = rr->Curvy;
  318.        if (Ranno & 64) ddx += 1;
  319.        if (Ranno & 1024) ddx -= 1;
  320.        if ((ddx > curve) || (ddx < (-curve))) ddx = rr->dx; }
  321.     rr->dx = ddx;
  322.     rr->X += ddx;
  323.     road(rr->X, rr->width, rr->Token);
  324.     return 0; }
  325.  
  326. /* returns 2 iff end, 0 iff crash, 1 else.    */
  327.  
  328. int Update()
  329.  {    int Eor;
  330.     SignY=32;
  331.     roll();
  332.